package com.nerins.udp.client;

import java.net.InetSocketAddress;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.DatagramConnector;
import org.apache.mina.transport.socket.nio.NioDatagramConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nerins.udp.server.RBACCodecFactory;
import com.nerins.udp.server.RBACResponse;
import com.nerins.udp.server.UDPServer;

/**
 * Sends its memory usage to the MemoryMonitor server.
 * 
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */

public class RBACClient extends IoHandlerAdapter {

	private final static Logger LOGGER = LoggerFactory
			.getLogger(RBACClient.class);

	private String host;
	private int port;
	private IoSession session;
	private RBACListener listener;

	private DatagramConnector connector;

	/**
	 * Default constructor.
	 */
	public RBACClient(String host, int port, RBACListener listener) {

		this.host = host;
		this.port = port;
		this.listener = listener;
		connector = new NioDatagramConnector();
		connector.getFilterChain().addLast("codec",
				new ProtocolCodecFilter(new RBACCodecFactory(true)));
		connector.setHandler(this);

	}

	private void send() {
		ConnectFuture connFuture = connector.connect(new InetSocketAddress(
				host, port));

		connFuture.addListener(new IoFutureListener() {
			public void operationComplete(IoFuture future) {
				ConnectFuture connFuture = (ConnectFuture) future;
				if (connFuture.isConnected()) {
					session = future.getSession();
					try {
						sendData();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				} else {
					LOGGER.error("Not connected...exiting");
				}
			}
		});

	}

	private void sendData() throws InterruptedException {

		long free = Runtime.getRuntime().freeMemory();
		IoBuffer buffer = IoBuffer.allocate(8);
		buffer.putLong(free);
		buffer.flip();
		session.write(buffer);

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new InterruptedException(e.getMessage());
		}
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		cause.printStackTrace();
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		LOGGER.debug("Session recv...");

		RBACResponse response = (RBACResponse) message;
		listener.onResponse(response);
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		LOGGER.debug("Message sent...");
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		LOGGER.debug("Session closed...");
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		LOGGER.debug("Session created...");
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		LOGGER.debug("Session idle...");
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		LOGGER.debug("Session opened...");
	}

	public static void main(String[] args) {
		RBACClient client = new RBACClient("localhost", 4444,
				new RBACListener());

		try {
			client.send();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
